<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <title>
    Yaf---异常和错误 | 路由和分发 |
    
    无敌小笼包</title>
  
    <link rel="shortcut icon" href="/favicon.png">
  
  <link rel="stylesheet" href="/css/style.css">
  
    <link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">
  
  <script src="/js/pace.min.js"></script>
</head>

<body>
<main class="content">
  <section class="outer">
  <article id="post-yaf04" class="article article-type-post" itemscope itemprop="blogPost">

  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      Yaf---异常和错误 | 路由和分发
    </h1>
  

      </header>
    

    
      <div class="article-meta">
        <a href="/2016/07/31/yaf04/" class="article-date">
  <time datetime="2016-07-31T15:00:43.000Z" itemprop="datePublished">2016-07-31</time>
</a>
        
  <div class="article-category">
    <a class="article-category-link" href="/categories/Frame/">Frame</a>
  </div>

      </div>
    

    <div class="article-entry" itemprop="articleBody">
      
      
      
        <p>Yaf实现了一套错误和异常捕获机制, 主要是对常见的错误处理和异常捕获方法做了一个简单抽象, 方便应用组织自己的错误统一处理逻辑。前题是需要配置过或是在程序中启用<br><a id="more"></a></p>
<h3 id="使用示例"><a href="#使用示例" class="headerlink" title="使用示例"></a>使用示例</h3><p>Yaf实现了一套错误和异常捕获机制, 主要是对常见的错误处理和异常捕获方法做了一个简单抽象, 方便应用组织自己的错误统一处理逻辑。前题是需要配置过或是在程序中启用</p>
<ul>
<li>配置</li>
</ul>
<pre><code>application.dispatcher.throwException=1
application.dispatcher.catchException=1
</code></pre><ul>
<li>在程序中启用</li>
</ul>
<blockquote>
<p><code>Yaf_Dispatcher::throwException(true)</code></p>
</blockquote>
<p>在<code>application.dispatcher.catchException</code>(配置文件, 或者可通过<code>Yaf_Dispatcher::catchException(true))</code>开启的情况下, 当Yaf遇到未捕获异常的时候, 就会把运行权限, 交给当前模块的<code>Error Controller</code>的<code>Error Action</code>动作, 而异常或作为请求的一个参数, 传递给<code>Error Action</code>.</p>
<p>新建一个Error Controller</p>
<pre><code>&lt;?php
class ErrorController extends Yaf_Controller_Abstract
{
    public function errorAction($exception)
    {
        assert($exception);
        $this-&gt;getView()-&gt;assign(&quot;code&quot;, $exception-&gt;getCode());
        $this-&gt;getView()-&gt;assign(&quot;message&quot;, $exception-&gt;getMessage());
        $this-&gt;getView()-&gt;assign(&quot;line&quot;, $exception-&gt;getLine());
    }
}
?&gt;
</code></pre><p>新建一个Error显示模板文件</p>
<pre><code>&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot;&gt;
&lt;title&gt;Error Page &lt;{$code}&gt;&lt;/title&gt;
    &lt;style&gt;
          body{background-color:#f0c040}
          h2{color:#fafafa}
    &lt;/style&gt;
&lt;/head&gt;
    &lt;body&gt;
          &lt;h2&gt;Error Page&lt;/h2&gt;
              &lt;p&gt;Error Code:&lt;{$code}&gt;&lt;/p&gt;
              &lt;p&gt;Error Message:&lt;{$message}&gt;&lt;/p&gt;
              &lt;p&gt;Error Line:&lt;{$line}&gt;&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre><p>在Bootstrap.php中新建一个error_handler方法</p>
<pre><code>public static function error_handler($errno, $errstr, $errfile, $errline)
{
    if (error_reporting() === 0) return;
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
</code></pre><p>在Bootstrap.php中初始化ErrorHandler</p>
<pre><code>public function _initErrorHandler(Yaf_Dispatcher $dispatcher)
{
      $dispatcher-&gt;setErrorHandler(array(get_class($this),&apos;error_handler&apos;));
}
</code></pre><p>这样当有有程序异常时会转到ErrorController</p>
<blockquote>
<p>路由和分发</p>
</blockquote>
<p>简单的理解</p>
<p>就我的理解来说，路由分发过程的执行动作是，获取用户请求的URl，根据路由规则解析这个URL，得到module、controller、action、param、query，根据获得的module和controller去载入控制器，执行对应的action方法。插件钩子路由器也有插件钩子,就是routerStartup和routerShutdown,他们在路由解析前后分别被调用.本文档使看构建 </p>
<blockquote>
<p>设置路由的方法</p>
</blockquote>
<ul>
<li>添加配置 </li>
</ul>
<pre><code>routes.regex4.type=&quot;regex&quot;
routes.regex4.match=&quot;#^/news/([^/])/([^/])#&quot;
routes.regex4.route.controller=news
routes.regex4.route.action=detail
routes.regex4.map.1=id
routesregex4map2=sort
</code></pre><ul>
<li>在Bootstapphp中添加路由配置</li>
</ul>
<pre><code>&lt;?php
  class Bootstrap extends Yaf_Bootstrap_Abstract{

    public function _initRoute(Yaf_Dispatcher $dispatcher) {

    $router = Yaf_Dispatcher::getInstance()-&gt;getRouter();

    $router-&gt;addConfig(Yaf_Registry::get(&quot;config&quot;)-&gt;routes);

    }
  }
</code></pre><ul>
<li>添加接收的控制器</li>
</ul>
<pre><code>&lt;?php
class NewsController extends Yaf_Controller_Abstract {

      public function init()
      {

           Yaf_Dispatcher::getInstance()-&gt;disableView();

      }
      public function detailAction($id = 0,$sort = &apos;&apos;)
      {

          print_r($this-&gt;getRequest()-&gt;getParams());

          echo &apos;News Detail:&apos;.$id.&apos;,sort:&apos;.$sort;

      }
}
?&gt;
</code></pre><ul>
<li>访问  url: yourhost/news/78/createtime</li>
</ul>
<p>当访问这个url，yaf先根据我们的路由规则解析出默认的module,news控制器,detailAction,第一个参数id,第二个参数，sort。</p>
<p>我们来分析一下解析流程：</p>
<pre><code>YafApplication::app()&gt;bootstrap()&gt;getDispatcher&gt;dispatch();
</code></pre><p>1.在yaf_dispatcher_route中，完成路由解析，得到module=’’，controller=news，action=detail</p>
<p>2.在yaf_dispatcher_fix_default中，通过其处理得到module=index，controller=news，action=detail</p>
<p>3.在2中完成之后，通过如果有hook机制，就会执行插件钩子：routerShutdown</p>
<p>4.在yaf_internal_autoload中完成自动加载类文件，application/controllers/News.php</p>
<p>5执行detailAction</p>
<p>在Bootstrapphp中配置路由规则</p>
<p>上面就是一个简单的通过正则的方式来设置路由的示例，我们还可以直接在Bootstrap.php添加我们的路由规则：</p>
<pre><code>public function _initRoute(Yaf_Dispatcher $dispatcher) {

      $router = Yaf_Dispatcher::getInstance()-&gt;getRouter();

      $router-&gt;addConfig(Yaf_Registry::get(&quot;config&quot;)-&gt;routes);

      //在刚才的示例里添加上下面两行

      $route = new Yaf_Route_Simple(&quot;m&quot;, &quot;c&quot;, &quot;a&quot;);

      $router-&gt;addRoute(&quot;simple&quot;, $route);
｝
</code></pre><p>测试一下</p>
<p>我们就可以尝试用 yourhost?c=news&amp;a=detail 访问你的newsController,detailAction了。</p>
<h3 id="Yaf-Route-Simple"><a href="#Yaf-Route-Simple" class="headerlink" title="Yaf_Route_Simple"></a>Yaf_Route_Simple</h3><p>上面是<code>Yaf_Route_Simple</code>的一个示例</p>
<p>Yaf_Route_Simple是基于请求中的query string来做路由的, 在初始化一个Yaf_Route_Simple路由协议的时候, 我们需要给出3个参数, 这3个参数分别代表在query string中Module, Controller, Action的变量名，它也可以直接在配置信息里设置</p>
<pre><code>routes.simple.type=&quot;simple&quot;
routes.simple.controller=c
routes.simple.module=m
routes.simple.action=a
</code></pre><p>更多关于路由的信息可以参见官方文档：<a href="http://www.laruence.com/manual/yaf.routes.static.html" target="_blank" rel="noopener">http://www.laruence.com/manual/yaf.routes.static.html</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://blog.mango16.cc/2016/07/31/yaf04/" data-id="cjrbtw1z400296d8hfd15we5e"
         class="article-share-link">分享</a>
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Yaf/">Yaf</a></li></ul>

    </footer>

  </div>

  
    
  <nav class="article-nav">
    
      <a href="/2016/09/10/swoole_1/" class="article-nav-link">
        <strong class="article-nav-caption">前一篇</strong>
        <div class="article-nav-title">
          
            swoole 学习第一章 Task进程与Timer进程
          
        </div>
      </a>
    
    
      <a href="/2016/07/30/yaf03/" class="article-nav-link">
        <strong class="article-nav-caption">后一篇</strong>
        <div class="article-nav-title">Yaf---Session | 模板 | 模型  | Cli模式</div>
      </a>
    
  </nav>


  

  
    
  <div class="gitalk" id="gitalk-container"></div>
  <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
  <script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>
  <script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
  <script type="text/javascript">
      var gitalk = new Gitalk({
        clientID: 'caba8826a61790936307',
        clientSecret: '09a15037dcab30d9adf35a53ec6961939169f797',
        repo: 'm9rco.github.io',
        owner: 'm9rco',
        admin: ['m9rco'],
        // id: location.pathname,      // Ensure uniqueness and length less than 50
        id: md5(location.pathname),
        distractionFreeMode: false  // Facebook-like distraction free mode
      })

  gitalk.render('gitalk-container')
  </script>

  

</article>



</section>
  <footer class="footer">
  
  <div class="outer">
    <ul class="list-inline">
      <li>&copy; 2019 无敌小笼包</li>
      <i class="pulse"></i>
    </ul>
  </div>
</footer>

</main>
<aside class="sidebar">
  <button class="navbar-toggle"></button>

<nav class="navbar">
  
    <div class="logo">
      <a href="/"><img src="/images/hexo.svg" alt="无敌小笼包"></a>
    </div>
  
  <ul class="nav nav-main">
    
      <li class="nav-item">
        <a class="nav-item-link" href="/">主页</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/archives">归档</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/gallery">相册</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/nagging">叽咕</a>
      </li>
    
      <li class="nav-item">
        <a class="nav-item-link" href="/about">关于</a>
      </li>
    
    <li class="nav-item">
      <a class="nav-item-link nav-item-search" title="Search">
        <i class="fe fe-search"></i>
        搜索
      </a>
    </li>
  </ul>
</nav>

<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
        <a class="nav-item-link" target="_blank" href="/atom.xml" title="RSS Feed">
          <i class="fe fe-feed"></i>
        </a>
      
    </li>
  </ul>
</nav>

<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
</aside>
  <script src="/js/jquery-2.0.3.min.js"></script>
<script src="/js/lazyload.min.js"></script>


  <script src="/fancybox/jquery.fancybox.min.js"></script>



  <script src="/js/search.js"></script>


<script src="/js/ocean.js"></script>

</body>
</html>